#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/10/4 10:57
# @Author  : summer
# @Email   : 610658552@qq.com
# @File    : utils_token.py
# @Software: PyCharm
# @Desc    :
import jwt
from django.conf import settings
from rest_framework import exceptions

from common.ext.auth import JwtHeaderAuthentication, JwtBodyAuthentication, JwtQueryParamsAuthentication
from common.models import Account


class TokenUtils(object):
    """Token工具类：兼容多渠道token获取，复用已有认证逻辑"""

    @staticmethod
    def get_token_from_request(request):
        """
        从请求中获取token，按以下优先级尝试：
        1. 请求头（Authorization）
        2. 请求体（data中的token字段）
        3. 查询参数（query_params中的token字段）
        与项目现有认证类逻辑保持一致
        """
        # 1. 尝试从请求头获取（JwtHeaderAuthentication逻辑）
        header_auth = JwtHeaderAuthentication()
        try:
            payload, token = header_auth.authenticate(request)
            if token:
                return token
        except:
            pass  # 未获取到则继续尝试其他渠道

        # 2. 尝试从请求体获取（JwtBodyAuthentication逻辑）
        body_auth = JwtBodyAuthentication()
        try:
            payload, token = body_auth.authenticate(request)
            if token:
                return token
        except:
            pass  # 未获取到则继续尝试其他渠道

        # 3. 尝试从查询参数获取（JwtQueryParamsAuthentication逻辑）
        query_auth = JwtQueryParamsAuthentication()
        try:
            payload, token = query_auth.authenticate(request)
            if token:
                return token
        except:
            pass

        # 所有渠道都未获取到token
        raise exceptions.AuthenticationFailed({"code": 401, "msg": "未提供有效的token"})

    @staticmethod
    def decode_token(token):
        """解析token，复用项目已有加密参数和异常处理"""
        try:
            # 与认证类保持一致的解密逻辑：使用SECRET_KEY和HS256算法
            payload = jwt.decode(
                token,
                settings.SECRET_KEY,
                algorithms=["HS256"],
                options={"verify_signature": True}
            )
            return payload
        except jwt.ExpiredSignatureError:
            raise exceptions.AuthenticationFailed({"code": 10000, "msg": "token已失效"})
        except jwt.DecodeError:
            raise exceptions.AuthenticationFailed({"code": 10001, "msg": "token认证失败"})
        except jwt.InvalidTokenError:
            raise exceptions.AuthenticationFailed({"code": 10002, "msg": "非法token"})

    @staticmethod
    def get_creator_info(request):
        """
        从请求中获取创建者完整信息
        流程：多渠道获取token -> 解析token -> 查询有效用户
        """
        try:
            # 1. 获取token（自动尝试所有渠道）
            token = TokenUtils.get_token_from_request(request)

            # 2. 解析token获取用户信息
            payload = TokenUtils.decode_token(token)
            creator_id = payload.get('id')  # 与登录时token_data中的id对应
            if not creator_id:
                raise exceptions.AuthenticationFailed({"code": 10003, "msg": "token中未包含用户ID"})

            # 3. 查询创建者账号（必须是有效账号）
            creator = Account.objects.get(
                id=creator_id,
                is_delete=0,
                pt_flag=0,
                status=1  # 确保账号处于启用状态
            )
            return creator

        except Account.DoesNotExist:
            raise exceptions.AuthenticationFailed({"code": 10004, "msg": "创建者账号不存在或已被禁用"})
        except exceptions.AuthenticationFailed as e:
            # 直接抛出已格式化的认证异常
            raise e
        except Exception as e:
            raise exceptions.AuthenticationFailed({"code": 10005, "msg": f"获取用户信息失败：{str(e)}"})

